﻿using CPPEI.Coolzon.Common;
using CPPEI.Coolzon.Event.Core;
using CPPEI.Coolzon.Event.NCL;
using CPPEI.Coolzon.Metadata;
using CPPEI.Coolzon.UI;
using CPPEI.Coolzon.UI.Data;
using CPPEI.Coolzon.UI.Event;
using CPPEI.Coolzon.UI.Views.Windows;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace CPPEI.Coolzon.Theme.Default.MainViewControl
{
    /// <summary>
    /// SceneImmediate.xaml 的交互逻辑
    /// </summary>
    public partial class SceneImmediate : UserControl
    {
        public Scene _Scene;
        public bool FromImmediate;
        public Label CurrentLable;

        private BorderWindow borderWindow;
        private Hook hook;
        private Point OldPoint;
        private Label OldBorder;
        private DispatcherTimer dispatcherTimer;
        private bool IsLongPress;

        public SceneImmediate()
        {
            InitializeComponent();

            hook = new Hook();

            hook.MouseLeftButtonMove += hook_MouseLeftButtonMove;
            hook.MouseLeftButtonUp += hook_MouseLeftButtonUp;
        }
        #region Hook
        void hook_MouseLeftButtonUp(double x, double y)
        {
            ClearEffect();
            if (borderWindow != null)
            {
                Label target = GetElementByPoint(new Point(x, y));
                Label source = borderWindow.Tag as Label;
                Swap(source, target);
            }
            CloseBorderWindow();
        }

        void hook_MouseLeftButtonMove(double x, double y)
        {
            Move(x, y);
        }
        private void Move(double x, double y)
        {
            if (OldPoint != null)
            {
                borderWindow.Left = borderWindow.Left + (x - OldPoint.X);
                borderWindow.Top = borderWindow.Top + (y - OldPoint.Y);

                Label target = GetElementByPoint(new Point(x, y));
                if (target != null)
                {
                    target.Style = GetEffectStyle();
                    if (OldBorder != null && target != OldBorder)
                    {
                        OldBorder.Style = GetOriginalStyle();
                    }
                    OldBorder = target;
                }
                else
                {
                    if (OldBorder != null)
                    {
                        OldBorder.Style = GetOriginalStyle();
                    }
                }
            }
            OldPoint = new Point(x, y);
        }
        private void CreateBorderWindow()
        {
            Label source = dispatcherTimer.Tag as Label;

            Point point = source.PointToScreen(new Point(0, 0));

            borderWindow = new BorderWindow();
            borderWindow.Left = point.X - 3;
            borderWindow.Top = point.Y - 3;
            borderWindow.Width = source.ActualWidth;
            borderWindow.Height = source.ActualHeight;
            borderWindow.Show();
            OldPoint = PointToScreen(System.Windows.Input.Mouse.GetPosition(this));
            hook.SetMouseHook();
            borderWindow.Tag = source;

            dispatcherTimer.IsEnabled = false;
        }
        private void Swap(Label source, Label target)
        {
            if (source != null && target != null)
            {
                target.Style = GetPressStyle();
                double targetLeft = Canvas.GetLeft(target);
                double sourceLeft = Canvas.GetLeft(source);
                Canvas.SetLeft(source, targetLeft);
                Canvas.SetLeft(target, sourceLeft);

                Area sourceArea = source.DataContext as Area;
                Area targetArea = target.DataContext as Area;
                //是否允许区域呼唤
                if (_Scene.IsAllowSwapArea)
                {
                    Common.EventBus.Instance.Publish(new SwapAreaEvent(_Scene.Name, source.Name, target.Name));
                }
            }
        }
        private void CloseBorderWindow()
        {
            if (borderWindow != null)
            {
                hook.UnLoadHook();
                borderWindow.Close();
                borderWindow = null;
            }
        }
        private Label GetElementByPoint(Point point)
        {
            foreach (UIElement element in _Layout.Children)
            {
                if (element is Label)
                {
                    Label label = element as Label;
                    Point startPoint = label.PointToScreen(new Point(0, 0));
                    Point endPoint = new Point(startPoint.X + label.ActualWidth, startPoint.Y + label.ActualHeight);

                    if (point.X >= startPoint.X && point.Y >= startPoint.Y && point.X <= endPoint.X && point.Y <= endPoint.Y)
                        return label;
                }
            }
            return null;
        }
        private void ClearEffect()
        {
            foreach (UIElement element in _Layout.Children)
            {
                if (element is Label)
                {
                    Label label = element as Label;
                    label.Style = GetOriginalStyle();
                }
            }
        }

        private void SetDispatchTime(object sender)
        {
            if (dispatcherTimer == null)
            {
                dispatcherTimer = new DispatcherTimer();
                dispatcherTimer.Interval = TimeSpan.FromMilliseconds(500);
                dispatcherTimer.Tick += dispatcherTimer_Tick;
            }
            dispatcherTimer.IsEnabled = true;
            dispatcherTimer.Tag = sender;
        }

        void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Arrow;
            IsLongPress = true;
            CreateBorderWindow();
        }

        #endregion
        public void BindSceneImmediate()
        {
            _Layout.Children.Clear();
            if (_Scene == null || _Scene.Areas == null || !_Scene.Areas.Any()) return;

            for (int i = 0; i < _Scene.Areas.Count; i++)
            {
                Area area = _Scene.Areas[i];
                Label lbl = new Label();
                lbl.Name = area.Name;
                lbl.Content = area.Caption;
                lbl.VerticalAlignment = VerticalAlignment.Center;

                lbl.MouseLeftButtonDown += lbl_MouseLeftButtonDown;
                lbl.MouseLeftButtonUp += lbl_MouseLeftButtonUp;
                lbl.MouseLeave += lbl_MouseLeave;
                lbl.DataContext = area;
                lbl.Style = GetOriginalStyle();

                //获取区域图片
                UI.Views.RenderView renderView = UIContext.Current.RenderView as UI.Views.RenderView;
                IPartContainer partContainer = renderView.GetCurrentPart() as IPartContainer;
                UI.Part part = partContainer.GetChildPart(area.Name, false);
                if (part != null)
                {
                    //将区域缩放到Label
                    lbl.Height = this.ActualHeight * 0.6;
                    lbl.Width = (part.ActualWidth / part.ActualHeight) * lbl.Height;
                    double left = (lbl.Height / part.ActualHeight) * part.XLeft;
                    Canvas.SetLeft(lbl, left);
                    Canvas.SetTop(lbl, (this.ActualHeight - lbl.Height) / 2);
                    left = left + lbl.Width;
                    //设置图片
                    lbl.Background = new VisualBrush(part);
                    _Layout.Children.Add(lbl);
                }
            }
        }
        private double GetScale(UI.Part part)
        {
            return (this.ActualHeight - 40) / part.ActualHeight;
        }
        void lbl_MouseLeave(object sender, MouseEventArgs e)
        {
            this.Cursor = Cursors.Arrow;
            if (IsLongPress || dispatcherTimer != null)
            {
                dispatcherTimer.IsEnabled = false;
            }
        }

        void lbl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (dispatcherTimer != null && dispatcherTimer.IsEnabled)
            {
                dispatcherTimer.IsEnabled = false;
            }
            if (!IsLongPress)
            {
                Label lbl = sender as Label;
                if (lbl == CurrentLable) return;

                Area area = lbl.DataContext as Area;
                Common.EventBus.Instance.Publish(new UI.Event.ScrollSceneEvent("", UIContext.Current.Solution, _Scene, area));

                lbl.Style = GetPressStyle();
                if (CurrentLable != null)
                {
                    CurrentLable.Style = GetOriginalStyle();
                }
                CurrentLable = lbl;
            }
            else
            {
                IsLongPress = false;
            }
            this.Cursor = Cursors.Arrow;
        }

        void lbl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.Cursor = Cursors.Wait;
            Label label = sender as Label;
            Area area = label.DataContext as Area;
            //是否允许区域互换
            if (_Scene.IsAllowSwapArea)
            {
                SetDispatchTime(sender);
            }
        }

        private Style GetOriginalStyle()
        {
            return (Style)_Layout.Resources["lblEnter"];
        }

        private Style GetPressStyle()
        {
            return (Style)_Layout.Resources["lblPress"];
        }

        private Style GetEffectStyle()
        {
            return (Style)_Layout.Resources["lblEffect"];
        }


        [Common.Subscribe]
        public void OnOpened(CoreOpenSceneCompletedEvent @event)
        {
            if (!FromImmediate && @event.SwitchMode != SwitchMode.Pop && (@event.FrameName == null || !@event.FrameName.Equals("root")))
            {
                _Scene = SolutionUtil.GetScene(UIContext.Current.Solution, @event.SceneName);
                BindSceneImmediate();
            }
            FromImmediate = false;
        }

        [Subscribe]
        public void OnSceneClosed(CoreCloseSceneCompletedEvent @event)
        {
        }

        [Subscribe]
        public void OnReceiveSwapAreaCompletedEvent(UI.Event.SwapAreaCompletedEvent swapAreaCompletedEvent)
        {
            BindSceneImmediate();
            //swapAreaCompletedEvent.DestArea=
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sizeInfo"></param>
        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            // 当程序第一次启动是，此区域还没有高度和宽度，在大小改变时需要重新绑定
            BindSceneImmediate();
            base.OnRenderSizeChanged(sizeInfo);
        }
    }
}
